using HtmlAgilityPack;
using System.Net;
using HtmlDocument = HtmlAgilityPack.HtmlDocument;

namespace Crawler
{
    public partial class Form1 : Form
    {
        private HashSet<string> visitedUrls = new HashSet<string>();
        private Queue<string> urlQueue = new Queue<string>();

        public Form1()
        {
            InitializeComponent();

            ContextMenuStrip listboxContextMenu = new ContextMenuStrip();
            ToolStripMenuItem copyMenuItem = new ToolStripMenuItem("复制");
            copyMenuItem.Click += CopyMenuItem_Click;
            listboxContextMenu.Items.Add(copyMenuItem);

            // 将上下文菜单关联到ListBox
            listBox1.ContextMenuStrip = listboxContextMenu;
            listBox2.ContextMenuStrip = listboxContextMenu;
        }

        private void CopyMenuItem_Click(object sender, EventArgs e)
        {
            ListBox lb = this.ActiveControl as ListBox; // 获取当前活动的ListBox
            if (lb != null && lb.SelectedItem != null)
            {
                // 将选中的内容复制到剪贴板
                Clipboard.SetText(lb.SelectedItem.ToString());
            }
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void label2_Click(object sender, EventArgs e)
        {

        }

        private async void button1_Click(object sender, EventArgs e)
        {
            visitedUrls.Clear();
            urlQueue.Clear();
            listBox1.Items.Clear();
            listBox2.Items.Clear();

            string startUrl = textBox1.Text;
            if (!string.IsNullOrWhiteSpace(startUrl))
            {
                urlQueue.Enqueue(startUrl);
                await Task.Run(() => Crawl());
            }
        }

        private void Crawl()
        {
            while (urlQueue.Count > 0)
            {
                string url = urlQueue.Dequeue();
                if (visitedUrls.Contains(url))
                {
                    continue;
                }

                this.Invoke(new Action(() => {
                    visitedUrls.Add(url);
                    listBox1.Items.Add(url);
                }));

                try
                {
                    var client = new WebClient();
                    string html = client.DownloadString(url);
                    var doc = new HtmlDocument();
                    doc.LoadHtml(html);

                    var nodes = doc.DocumentNode.SelectNodes("//a[@href]");
                    if (nodes is null)
                    {
                        continue;
                    }

                    foreach (HtmlNode link in nodes)
                    {
                        string hrefValue = link.GetAttributeValue("href", string.Empty);
                        string newUrl = hrefValue.StartsWith("http") ? hrefValue : new Uri(new Uri(url), hrefValue).ToString();
                        if (newUrl.StartsWith(textBox1.Text))
                        {
                            urlQueue.Enqueue(newUrl);
                        }
                    }
                }
                catch (Exception ex)
                {
                    this.Invoke(new Action(() => {
                        listBox2.Items.Add($"{url}: {ex.Message}");
                    }));
                }
            }
        }
    }
}
